package ar.edu.itba.it.cg.grupo01.impl;

import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import ar.edu.itba.it.cg.grupo01.api.Intersection;
import ar.edu.itba.it.cg.grupo01.api.Ray;
import ar.edu.itba.it.cg.grupo01.api.scene.Scene;
import ar.edu.itba.it.cg.grupo01.api.shape.Shape;
import ar.edu.itba.it.cg.grupo01.impl.RayTracer.ColorHolder;
import ar.edu.itba.it.cg.grupo01.impl.scene.optimization.Octree;
import ar.edu.itba.it.cg.grupo01.impl.shape.Triangle;

public class RayTraceInformation {
	private RayTracer tracer;
	private Octree octree;
	private Vector3f normal;
	private Vector3f reflectedRayDir;
	private Shape shape;
	private ColorHolder color;
	private ColorHolder reflectionColor = new ColorHolder();
	private ColorHolder refractionColor = new ColorHolder();
	private Intersection<? extends Shape> intersection;
	private Ray ray;
	private Point3f intersectionPoint;
	private Scene scene;

	public RayTraceInformation(RayTracer rayTracer, Scene scene,Octree octree,
			Ray ray, ColorHolder color,
			Shape shape, Intersection<? extends Shape> intersection) {
		this.tracer = rayTracer;
		this.octree = octree;
		this.scene = scene;
		this.ray = ray;
		this.color = color;
		this.shape = shape;
		this.intersection = intersection;
		this.intersectionPoint = intersection.closestTo(ray.getOrigin());
	}

	public RayTracer getTracer() {
		return tracer;
	}

	public Vector3f getNormal() {
		if (normal == null) {
			normal = shape.getNormal(intersectionPoint);
		}
		return normal;
	}

	public Vector3f getReflectedDirection(Intersection.Type intersectionType) {
		if (reflectedRayDir == null) {
			Vector3f facedNormal = new Vector3f(getNormal());
			Vector3f direction = getRay().getDirection();

			if (this.getShape() instanceof Triangle) {
				if (facedNormal.dot(direction) < 0) {
					facedNormal.negate();
				}
			} else if (intersectionType.equals(Intersection.Type.IN)) {
				facedNormal.negate();
			}

			float dot = facedNormal.dot(direction);

			facedNormal.scale(2.0f * dot);
			reflectedRayDir = new Vector3f();
			reflectedRayDir.sub(direction, facedNormal);
			reflectedRayDir.normalize();
		}

		return reflectedRayDir;
	}

	public Shape getShape() {
		return shape;
	}

	public ColorHolder getColor() {
		return color;
	}

	public void setColor(ColorHolder color) {
		this.color = color;
	}

	public Intersection<? extends Shape> getIntersection() {
		return intersection;
	}

	public Ray getRay() {
		return ray;
	}

	public Octree getOctree() {
		return octree;
	}

	public Scene getScene() {
		return scene;
	}

	public void setReflectionColor(ColorHolder reflectionColor) {
		this.reflectionColor = reflectionColor;
	}

	public ColorHolder getReflectionColor() {
		return reflectionColor;
	}

	public void setRefractionColor(ColorHolder refractionColor) {
		this.refractionColor = refractionColor;
	}

	public ColorHolder getRefractionColor() {
		return refractionColor;
	}

	public Point3f getIntersectionPoint() {
		return intersectionPoint;
	}
}
